Fix recursive type dependency collection issue#195
Merged
branchseer merged 3 commits intomainfrom Mar 4, 2026
Merged
Conversation
The DeclCollector in generate_ts_definition only called visit_dependencies on UserRunConfig, collecting direct dependencies but missing indirect ones. This meant any type referenced through a chain of dependencies (e.g. a type used by EnabledCacheConfig, which is flattened into UserTaskConfig) would be referenced in the generated TypeScript but never declared. Fix the collector to recursively visit each type's dependencies, using a HashSet<TypeId> to prevent infinite loops from circular references. Also add CacheOutputs as an indirect type (referenced through the flatten chain) that confirms the fix works — it's now properly declared in the generated run-config.ts. https://claude.ai/code/session_01VQvSgXNnYL8tNWydvtbCvg
Remove the CacheOutputs indirect type that was added to demonstrate the bug. The recursive DeclCollector fix is retained. https://claude.ai/code/session_01VQvSgXNnYL8tNWydvtbCvg
fengmk2
approved these changes
Mar 4, 2026
branchseer
added a commit
that referenced
this pull request
Mar 5, 2026
## Summary - The `DeclCollector` in `generate_ts_definition` only called `visit_dependencies` on `UserRunConfig`, which per the `ts_rs` API only visits **direct** type dependencies. Any type referenced indirectly through a chain of dependencies (e.g. a type nested inside a flattened struct) would appear in the generated TypeScript output but never be declared as its own type. - Fix the collector to recursively call `T::visit_dependencies(self)` for each visited type, using a `HashSet<TypeId>` to prevent infinite loops from circular references. - Add an auto-generated header comment to `run-config.ts` to make it clear the file should not be edited manually. ### Why this matters The bug is latent today because all indirect types happen to be `#[serde(flatten)]`-ed, which causes `ts_rs` to inline their fields rather than emit separate type declarations. But as soon as a non-flattened custom type is added at depth > 1 (e.g. a struct referenced by `EnabledCacheConfig`), the generated TypeScript would reference that type by name without ever declaring it — producing invalid TypeScript. The recursive fix future-proofs the collector so any new nested types are automatically included. The new `UserGlobalCacheConfig` type (added on `main`) is now correctly emitted thanks to this fix. ## Test plan - [x] `cargo test -p vite_task_graph` — all 14 tests pass - [x] `cargo check` — full project compiles cleanly - [x] Generated `run-config.ts` includes header and all types https://claude.ai/code/session_01VQvSgXNnYL8tNWydvtbCvg --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DeclCollectoringenerate_ts_definitiononly calledvisit_dependenciesonUserRunConfig, which per thets_rsAPI only visits direct type dependencies. Any type referenced indirectly through a chain of dependencies (e.g. a type nested inside a flattened struct) would appear in the generated TypeScript output but never be declared as its own type.T::visit_dependencies(self)for each visited type, using aHashSet<TypeId>to prevent infinite loops from circular references.run-config.tsto make it clear the file should not be edited manually.Why this matters
The bug is latent today because all indirect types happen to be
#[serde(flatten)]-ed, which causests_rsto inline their fields rather than emit separate type declarations. But as soon as a non-flattened custom type is added at depth > 1 (e.g. a struct referenced byEnabledCacheConfig), the generated TypeScript would reference that type by name without ever declaring it — producing invalid TypeScript. The recursive fix future-proofs the collector so any new nested types are automatically included. The newUserGlobalCacheConfigtype (added onmain) is now correctly emitted thanks to this fix.Test plan
cargo test -p vite_task_graph— all 14 tests passcargo check— full project compiles cleanlyrun-config.tsincludes header and all typeshttps://claude.ai/code/session_01VQvSgXNnYL8tNWydvtbCvg